<template>
  <div style="width: 100%; height: 100%">
    <!-- 图片上传组件辅助-->
    <el-upload
      accept=".jpg, .jpeg, .png, .JPG, .JPEG, .PBG"
      style="height: 0"
      action=""
      class="img-uploader"
      :multiple="false"
      :show-file-list="false"
      :before-upload="beforeUpload"
      :http-request="uploadFile"
    />
    <quill-editor
      ref="myQuillEditor"
      v-model="content"
      class="editor"
      :options="editorOption"
      @blur="onEditorBlur($event)"
      @focus="onEditorFocus($event)"
      @change="onEditorChange($event)"
    />
    <div>
      <el-dialog :close-on-click-modal="false" width="50%" style="margin-top: 1px" title="视频上传" :visible.sync="videoForm.show" append-to-body>
        <el-upload v-loading="loading" :show-file-list="false" class="video-uploader" style="text-align: center;" drag action="" accept="video/*" :before-upload="onBeforeUploadVideo" :http-request="uploadVideo" :multiple="false">
          <i class="el-icon-upload" />
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
          <div slot="tip" class="el-upload__tip">只能上传MP4文件，且不超过{{ uploadVideoConfig.maxSize }}M</div>
        </el-upload>
      </el-dialog>
    </div>
    <span v-if="showMessage" style="color: #ff0000; font-size: 12px; line-height: 20px">请编辑文档</span>
  </div>
</template>
<script>
// 工具栏配置
import { quillEditor } from 'vue-quill-editor';
import Video from './video';
import Quill from 'quill'; // 引入编辑器
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import axios from 'axios';
import ImageResize from 'quill-image-resize-module';
import { ImageDrop } from 'quill-image-drop-module';
// 设置title
import { addQuillTitle } from './quill-title.js'
// 设置行高
const Parchment = Quill.import('parchment');
class LineHeightAttributor extends Parchment.Attributor.Style {}
const lineHeightStyle = new LineHeightAttributor('lineHeight', 'line-height', {
  scope: Parchment.Scope.INLINE,
  whitelist: ['initial', '1', '1.5', '1.75', '2', '3', '4', '5']
});
Quill.register({ 'formats/lineHeight': lineHeightStyle }, true);

// 设置字体大小
const fontSize = ['10px', '12px', '14px', '16px', '18px', '20px', '22px', '24px', '26px', '32px', '48px'];
Quill['imports']['attributors/style/size'].whitelist = fontSize;
Quill.register(Quill['imports']['attributors/style/size']);

// 设置字体样式
const fontFamily = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong'];
Quill['imports']['formats/font'].whitelist = fontFamily;
Quill.register(Quill['imports']['formats/font']);

Quill.register('modules/imageDrop', ImageDrop); // 注册
Quill.register('modules/imageResize', ImageResize);
Quill.register(Video, true);

const toolbarOptions = [
  ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
  ['blockquote', 'code-block'], // 引用  代码块
  [{ header: 1 }, { header: 2 }], // 1、2 级标题
  [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
  [{ script: 'sub' }, { script: 'super' }], // 上标/下标
  [{ indent: '-1' }, { indent: '+1' }], // 缩进
  // [{'direction': 'rtl'}],                         // 文本方向
  // [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
  [{ size: fontSize }], // 字体大小
  [{ lineheight: ['initial', '1', '1.5', '1.75', '2', '3', '4', '5'] }],
  [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  // [{ font: [] }], // 字体种类
  [{ font: fontFamily }], // 字体
  [{ align: [] }], // 对齐方式
  ['clean'], // 清除文本格式
  ['link', 'image', 'video'] // 链接、图片、视频
];

// 工具栏鼠标悬浮中文提示
const titleConfig = [
  { Choice: '.ql-insertMetric', title: '跳转配置' },
  { Choice: '.ql-bold', title: '加粗' },
  { Choice: '.ql-italic', title: '斜体' },
  { Choice: '.ql-underline', title: '下划线' },
  { Choice: '.ql-header', title: '段落格式' },
  { Choice: '.ql-strike', title: '删除线' },
  { Choice: '.ql-blockquote', title: '块引用' },
  { Choice: '.ql-code', title: '插入代码' },
  { Choice: '.ql-code-block', title: '插入代码段' },
  { Choice: '.ql-font', title: '字体' },
  { Choice: '.ql-size', title: '字体大小' },
  { Choice: '.ql-list[value="ordered"]', title: '编号列表' },
  { Choice: '.ql-list[value="bullet"]', title: '项目列表' },
  { Choice: '.ql-direction', title: '文本方向' },
  { Choice: '.ql-header[value="1"]', title: 'h1' },
  { Choice: '.ql-header[value="2"]', title: 'h2' },
  { Choice: '.ql-align', title: '对齐方式' },
  { Choice: '.ql-color', title: '字体颜色' },
  { Choice: '.ql-background', title: '背景颜色' },
  { Choice: '.ql-image', title: '图像' },
  { Choice: '.ql-video', title: '视频' },
  { Choice: '.ql-link', title: '添加链接' },
  { Choice: '.ql-formula', title: '插入公式' },
  { Choice: '.ql-clean', title: '清除字体格式' },
  { Choice: '.ql-script[value="sub"]', title: '下标' },
  { Choice: '.ql-script[value="super"]', title: '上标' },
  { Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
  { Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
  { Choice: '.ql-header .ql-picker-label', title: '标题大小' },
  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
  { Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
  { Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
];

export default {
  name: 'RichTextEditor',
  components: {
    quillEditor
  },
  props: {
    /* 编辑器的内容 */
    value: {
      type: String,
      default: ''
    },
    /* 图片大小 */
    maxSize: {
      type: Number,
      default: 10000 // kb
    },
    showMessage: {
      type: Boolean,
      default: false
    },
    // 视频上传配置
    uploadVideoConfig: {
      type: Object,
      default() {
        return {
          uploadUrl: window.location.origin + '/api/material/upload', // 上传地址
          maxSize: 1000, // 视频上传大小限制，默认不超过2M
          name: 'file' // 图片上传字段
        }
      }
    }
  },
  data() {
    const that = this;
    return {
      loading: false, // 加载loading
      content: this.value,
      quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画，刚开始是false,不显示
      editorOption: {
        theme: 'snow', // or 'bubble'
        placeholder: '请编辑',
        modules: {
          toolbar: {
            container: toolbarOptions,
            // container: "#toolbar",
            handlers: {
              image: function(value) {
                if (value) {
                  // 触发input框选择图片文件
                  document.querySelector('.img-uploader input').click();
                } else {
                  this.quill.format('image', false);
                }
              },
              video: function(value) {
                // 覆盖默认的上传视频
                that.videoForm.show = true
              },
              lineheight: function(value) {
                // 行高相关
                if (value) {
                  this.quill.format('lineHeight', value);
                } else {
                  console.log(value);
                }
              }
              // link: function(value) {
              //   if (value) {
              //     var href = prompt('请输入url');
              //     this.quill.format("link", href);
              //   } else {
              //     this.quill.format("link", false);
              //   }
              // },
            }
          },
          history: {
            delay: 1000,
            maxStack: 50,
            userOnly: false
          },
          imageDrop: true,
          imageResize: {
            displayStyles: {
              backgroundColor: 'black',
              border: 'none',
              color: 'white'
            },
            modules: ['Resize', 'DisplaySize', 'Toolbar']
          }
        }
      },
      // serverUrl: process.env.VUE_APP_BASE_API + '/api/material/upload', // 这里写你要上传的图片服务器地址
      serverUrl: '',
      header: {
        token: this.$store.state.user.user_token
      }, // 有的图片服务器要求请求头需要有token
      // 视频上传变量
      videoForm: {
        show: false, // 显示插入视频链接弹框的标识
        videoLink: '',
        activeName: 'first'
      }
    };
  },
  watch: {
    value: {
      deep: true,
      handler(n, o) {
        if (n !== o) {
          this.content = n;
        }
      }
    }
  },
  created() {
    this.serverUrl = window.location.origin + '/api/material/upload'
  },
  mounted() {
    this.initTitle();
    // 初始给编辑器设置title
    addQuillTitle()
  },

  methods: {
    onEditorBlur() {
      // 失去焦点事件
      this.$emit('editorBlur')
    },
    onEditorFocus() {
      // 获得焦点事件
    },
    onEditorChange() {
      // 内容改变事件
      this.$emit('input', this.content);
    },
    hideLoading() {
      this.loading = false
    },
    // 富文本图片上传前
    beforeUpload() {
      // 显示loading动画
      this.quillUpdateImg = true;
    },
    uploadFile(file) {
      const that = this;
      const form = new FormData();
      form.append('file', file.file);
      return axios({
        // url: process.env.VUE_APP_BASE_API + '/api/material/upload',
        url: window.location.origin + '/api/material/upload',
        method: 'post',
        data: form,
        headers: { 'Content-Type': 'multipart/form-data' }
      }).then(res => that.uploadSuccess(res.data)).catch(() => that.uploadError());
    },
    uploadSuccess(res) {
      // res为图片服务器返回的数据
      // 获取富文本组件实例
      const quill = this.$refs['myQuillEditor'].quill;
      // 如果上传成功
      if (res.code === 200) {
        // 获取光标所在位置
        const length = quill.getSelection() ? quill.getSelection().index : 0;
        console.log('indexImage', length)
        // quill.insertEmbed(length, 'image', process.env.VUE_APP_BASE_API + '/api/' + res.data.url);
        quill.insertEmbed(length, 'image', window.location.origin + '/api/' + res.data.url);
        // 调整光标到最后
        quill.setSelection(length + 1);
      } else {
        this.$message.error('图片插入失败');
      }
      // loading动画消失
      this.quillUpdateImg = false;
    },
    // 富文本图片上传失败
    uploadError() {
      // loading动画消失
      this.quillUpdateImg = false;
      this.$message.error('图片插入失败');
    },
    // 行高相关
    ready() {
      Quill.register({ 'formats/lineHeight': lineHeightStyle }, true);
    },
    initTitle() {
      document.getElementsByClassName('ql-editor')[0].dataset.placeholder = '';
      for (const item of titleConfig) {
        const tip = document.querySelector('.quill-editor ' + item.Choice);
        if (!tip) continue;
        tip.setAttribute('title', item.title);
      }
    },
    /** --------- 视频上传相关 start ---------  */
    uploadVideo(file) {
      const that = this;
      const form = new FormData();
      form.append('file', file.file);
      return axios({
        // url: process.env.VUE_APP_BASE_API + '/api/material/upload',
        url: window.location.origin + '/api/material/upload',
        method: 'post',
        data: form,
        headers: { 'Content-Type': 'multipart/form-data' }
      }).then(res => that.onSuccessVideo(res.data)).catch(() => that.onErrorVideo());
    },
    insertVideoLink(videoLink) {
      if (!videoLink) return this.$message.error('视频地址不能为空！')
      this.videoForm.show = false
      const quill = this.$refs['myQuillEditor'].quill
      // 获取富文本
      // const range = quill.getSelection() //这种写法会和上面插入图片写法冲突 拿不到光标所在位置 range返回一只是null 不清楚为什么
      // 获取光标位置：当编辑器中没有输入文本时，这里获取到的 range 为 null
      // const index = range ? range.index : 0
      const index = quill.selection.savedRange.index;
      console.log('indexVideo', index)
      // 在光标所在位置 插入视频
      quill.insertEmbed(index, 'video', window.location.origin + '/api/' + videoLink)
      // 调整光标到最后
      quill.setSelection(index + 1)
    },
    // el-文件上传组件
    onBeforeUploadVideo(file) {
      this.loading = true
      const acceptArr = ['video/mp4']
      const isVideo = acceptArr.includes(file.type)
      const isLt1M = file.size / 1024 / 1024 < this.uploadVideoConfig.maxSize
      if (!isVideo) {
        this.hideLoading()
        this.$message.error('只能上传mp4格式文件!')
      }
      if (!isLt1M) {
        this.hideLoading()
        this.$message.error(`上传文件大小不能超过 ${this.uploadVideoConfig.maxSize}MB!`)
      }
      return isLt1M && isVideo
    },
    // 文件上传成功时的钩子
    onSuccessVideo(res) {
      this.hideLoading()
      if (res.code === 200) {
        // console.log('res.data.url', res.data.url)
        this.insertVideoLink(res.data.url)
      } else {
        this.$message.error('视频插入失败')
      }
    },
    // 文件上传失败时的钩子
    onErrorVideo() {
      this.hideLoading()
      this.$message.error('视频上传失败')
    }
    /** --------- 视频上传相关 end --------- */
  }
};
</script>

<style lang="scss">
.editor {
  border: 1px #ccc solid;
  border-top: none;
  background-color: #fff;
  width: 100%;
  height: 100%;
}

.ql-container.ql-snow {
  border: none;
}

.ql-toolbar.ql-snow {
  border: none;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;;
}

.editor {
  line-height: normal !important;
  min-height: 400px;
}

.ql-snow .ql-tooltip[data-mode=link]::before {
  content: "请输入链接地址:";
}

.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: '保存';
  padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode=video]::before {
  content: "请输入视频地址:";
}

// .ql-snow .ql-picker.ql-size .ql-picker-label::before,
// .ql-snow .ql-picker.ql-size .ql-picker-item::before {
//   content: '14px';
// }

// .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
// .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
//   content: '10px';
// }

// .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
// .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
//   content: '18px';
// }

// .ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
// .ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
//   content: '32px';
// }

.ql-container {
  font-size: 14px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="10px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="10px"]::before {
  content: '10px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
  content: '12px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
  content: '14px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
  content: '16px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
  content: '18px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
  content: '20px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {
  content: '22px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
  content: '24px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {
  content: '26px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {
  content: '32px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="48px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="48px"]::before {
  content: '48px';
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: '文本';
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: '标题1';
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: '标题2';
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: '标题3';
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: '标题4';
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: '标题5';
}

.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: '标题6';
}

// .ql-snow .ql-picker.ql-font .ql-picker-label::before,
// .ql-snow .ql-picker.ql-font .ql-picker-item::before {
//   content: '标准字体';
// }

// .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
// .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
//   content: '衬线字体';
// }

// .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
// .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
//   content: '等宽字体';
// }

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='SimSun']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='SimSun']::before {
  content: '宋体';
  font-family: 'SimSun' !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='SimHei']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='SimHei']::before {
  content: '黑体';
  font-family: 'SimHei';
}
.ql-snow
  .ql-picker.ql-font
  .ql-picker-label[data-value='Microsoft-YaHei']::before,
.ql-snow
  .ql-picker.ql-font
  .ql-picker-item[data-value='Microsoft-YaHei']::before {
  content: '微软雅黑';
  font-family: 'Microsoft YaHei';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='KaiTi']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='KaiTi']::before {
  content: '楷体';
  font-family: 'KaiTi' !important;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='FangSong']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='FangSong']::before {
  content: '仿宋';
  font-family: 'FangSong';
}

.ql-font-SimSun {
  font-family: 'SimSun';
}
.ql-font-SimHei {
  font-family: 'SimHei';
}
.ql-font-Microsoft-YaHei {
  font-family: 'Microsoft YaHei';
}
.ql-font-KaiTi {
  font-family: 'KaiTi';
}
.ql-font-FangSong {
  font-family: 'FangSong';
}

.editerVideo {
  width: 100%;
}

.editerVideo_title {
  display: flex;
  height: 30px;
  line-height: 30px;
  width: 100%;
  color: #1f2f3d;
  font-weight: bold;
  justify-content: flex-start;
  border-bottom: 2px solid #DCDFE6;
}

.editerVideo_title_act {
  color: #409eff;
  border-bottom: 2px solid #409eff;
  margin-bottom: -2px;
}

.editerVideo_title_item {
  margin-right: 10px;
}

.editerVideo_main {
  width: 100%;
}
.video-config-row{
  display: flex;
  justify-content: space-between;
  line-height: 30px;
}
.editerVideo_main_url {
  width: 100%;
  line-height: 30px;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  margin-top: 35px;
}

.avatar-uploader_video {
  width: 100px;
  height: 100px;
  border: 1px solid #D9D9D9;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 30px;
}

.avatar-uploader-videoiocn {
  font-size: 28px;
  color: #D9D9D9;
  line-height: 90px;
  text-align: center;
}

.videoProgress {
  margin-top: 30px;
}

.quillWidthmain {
  width: 800px;
  height: 320px;
}

.quillWidth {
  width: 800px;
  height: 270px;
}

//配置编辑器行高
.ql-snow .ql-picker.ql-lineheight .ql-picker-label::before {
  content: '行高';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='initial']::before {
  content: '默认';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='1']::before {
  content: '1';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='1.5']::before {
  content: '1.5';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='1.75']::before {
  content: '1.75';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='2']::before {
  content: '2';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='3']::before {
  content: '3';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='4']::before {
  content: '4';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='5']::before {
  content: '5';
}
.ql-snow .ql-picker.ql-lineheight {
  width: 70px;
}
</style>
